#include "framelesswindow.h"
#include <QDebug>
#include <QGuiApplication>
FramelessWindow::FramelessWindow(QWindow *parent)
{
    this->setFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
    // this->setIcon(QIcon("qrc:/icon/logo.ico"));
}

void FramelessWindow::mousePressEvent(QMouseEvent *event)
{
    this->resizeing = true;
    this->resizeCursor = this->cursor().shape();
    this->start_pos = event->globalPosition();
    this->old_pos = this->position();
    this->old_size = this->size();
    event->ignore();
    QQuickWindow::mousePressEvent(event);
}

void FramelessWindow::mouseReleaseEvent(QMouseEvent *event)
{
    this->old_pos = this->position();
    this->resizeing = false;
    QQuickWindow::mouseReleaseEvent(event);
}

void FramelessWindow::mouseMoveEvent(QMouseEvent *event)
{
    QPointF pos = event->position();
    if (event->buttons() & Qt::LeftButton) {
        this->setWindowGeometry(event->globalPosition());
    } else {
        this->mouse_pos = this->getMousePos(pos);
    }
    this->setCursorIcon();
    QQuickWindow::mouseMoveEvent(event);
}

void FramelessWindow::showEvent(QShowEvent *event)
{
    QQuickWindow::showEvent(event);
}

void FramelessWindow::setWindowGeometry(const QPointF &pos)
{
    QPointF offset = this->start_pos - pos;
    if (offset.x() == 0 && offset.y() == 0) return;
    static auto set_geometry_func = [this](const QSize &size, const QPointF &pos){
                                        QPointF t_pos = this->old_pos;
                                        QSize t_size = minimumSize();
                                        if (size.width() > minimumWidth()) {
                                            t_pos.setX(pos.x());
                                            t_size.setWidth(size.width());
                                        } else if (mouse_pos == LEFT || mouse_pos == TOPLEFT
                                                   || mouse_pos == BOTTOMLEFT) {
                                            t_pos.setX(old_pos.x()+old_size.width()-minimumWidth());
                                        }

                                        if (size.height() > minimumHeight()) {
                                            t_pos.setY(pos.y());
                                            t_size.setHeight(size.height());
                                        } else if (mouse_pos == TOP || mouse_pos == TOPLEFT
                                                   || mouse_pos == TOPRIGHT) {
                                            t_pos.setY(old_pos.y()+old_size.height()
                                                       -minimumHeight());
                                        }

                                        this->setGeometry(t_pos.x(), t_pos.y(), t_size.width(),
                                                          t_size.height());
                                        this->update();
                                    };
    switch (this->mouse_pos) {
    case TOP:
        set_geometry_func(this->old_size+QSize(0, offset.y()),
                          this->old_pos - QPointF(0, offset.y()));
        break;
    case TOPLEFT:
        set_geometry_func(this->old_size+QSize(offset.x(), offset.y()),
                          this->old_pos - offset);
        break;
    case TOPRIGHT:
        set_geometry_func(this->old_size+QSize(-offset.x(), offset.y()),
                          this->old_pos- QPointF(0, offset.y()));
        break;
    case LEFT:
        set_geometry_func(this->old_size+QSize(offset.x(), 0),
                          this->old_pos- QPointF(offset.x(), 0));
        break;
    case RIGHT:
        set_geometry_func(this->old_size+QSize(-offset.x(), 0),
                          this->old_pos);
        break;
    case BOTTOM:
        set_geometry_func(this->old_size+QSize(0, -offset.y()),
                          this->old_pos);
        break;
    case BOTTOMLEFT:
        set_geometry_func(this->old_size+QSize(offset.x(), -offset.y()),
                          this->old_pos-QPointF(offset.x(), 0));
        break;
    case BOTTOMRIGHT:
        set_geometry_func(this->old_size+QSize(-offset.x(), -offset.y()),
                          this->old_pos);
        break;
    default:
        break;
    }
}

void FramelessWindow::setCursorIcon()
{
    static bool isSet = false;
    if (this->resizeing) {
        this->setCursor(this->resizeCursor);
        return;
    }

    switch (this->mouse_pos) {
    case TOPLEFT:
    case BOTTOMRIGHT:
        this->setCursor(Qt::SizeFDiagCursor);
        isSet = true;
        break;
    case TOPRIGHT:
    case BOTTOMLEFT:
        this->setCursor(Qt::SizeBDiagCursor);
        isSet = true;
        break;
    case TOP:
    case BOTTOM:
        this->setCursor(Qt::SizeVerCursor);
        isSet = true;
        break;
    case LEFT:
    case RIGHT:
        this->setCursor(Qt::SizeHorCursor);
        isSet = true;
        break;
    default:
        if (isSet) {
            isSet = false;
            this->unsetCursor();
        }
        break;
    }
}

FramelessWindow::MousePostition FramelessWindow::getMousePos(QPointF &pos)
{
    int x = pos.x();
    int y = pos.y();
    int w = this->width();
    int h = this->height();

    MousePostition mouse_pos = NORMAL;

    if (x > 0 && x <= this->step && y >= 0 && y <= this->step) {
        mouse_pos = TOPLEFT;
    } else if (x < w && x >= w-this->step && y >= 0 && y <= this->step) {
        mouse_pos = TOPRIGHT;
    } else if (y >= 0 && y <= this->step) {
        mouse_pos = TOP;
    } else if (x >= 0 && x <= this->step && y > this->step && y < (h-this->step)) {
        mouse_pos = LEFT;
    } else if (x >= w-this->step && x <= w && y > this->step && y < (h-this->step)) {
        mouse_pos = RIGHT;
    } else if (x >= 0 && x <= this->step && y > (h-this->step) && y <= h) {
        mouse_pos = BOTTOMLEFT;
    } else if (x >= w-this->step && x <= w && y > (h-this->step) && y <= h) {
        mouse_pos = BOTTOMRIGHT;
    } else if (y > (h-this->step) && y <= h) {
        mouse_pos = BOTTOM;
    }
    return mouse_pos;
}

bool FramelessWindow::getResizeing() const
{
    return resizeing;
}

void FramelessWindow::setResizeing(bool newResizeing)
{
    if (resizeing == newResizeing)
        return;
    resizeing = newResizeing;
    emit resizeingChanged();
}

FramelessWindow::MousePostition FramelessWindow::getMouse_pos() const
{
    return mouse_pos;
}

void FramelessWindow::setMouse_pos(MousePostition newMouse_pos)
{
    if (mouse_pos == newMouse_pos)
        return;
    mouse_pos = newMouse_pos;
    emit mouse_posChanged();
}
